package com.ecommerce.service.impl;

import com.ecommerce.account.BalanceInfo;
import com.ecommerce.dao.EcommerceBalanceDao;
import com.ecommerce.entity.EcommerceBalance;
import com.ecommerce.filter.AccessContext;
import com.ecommerce.service.BalanceService;
import com.ecommerce.vo.LoginUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用于余额相关的服务接口实现
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class BalanceServiceImpl implements BalanceService {

    private final EcommerceBalanceDao balanceDao;

    public BalanceServiceImpl(EcommerceBalanceDao balanceDao) {
        this.balanceDao = balanceDao;
    }

    /**
     * 获取当前用户账户余额
     */
    @Override
    public BalanceInfo getCurrentUserBalanceInfo() {
        LoginUserInfo loginUserInfo = AccessContext.getLoginUserInfo();
        BalanceInfo balanceInfo = new BalanceInfo(loginUserInfo.getId(), 0L);
        EcommerceBalance ecommerceBalance = balanceDao.findByUserId(loginUserInfo.getId());
        if (ecommerceBalance == null) {
            // 如果还没有用户余额记录，这里可以直接进行创建
            EcommerceBalance newBalance = new EcommerceBalance();
            newBalance.setUserId(loginUserInfo.getId());
            newBalance.setBalance(0L);
            log.info("init user balance record: [{}]", balanceDao.save(newBalance).getId());
        }else {
            balanceInfo.setBalance(ecommerceBalance.getBalance());
        }

        return balanceInfo;
    }

    /**
     * 扣减当前用户账户余额
     * @param balanceInfo 代表想要扣减的余额, 并不是真实的余额
     */
    @Override
    public BalanceInfo deductBalance(BalanceInfo balanceInfo) {

        LoginUserInfo loginUserInfo = AccessContext.getLoginUserInfo();

        // 扣减用户余额的一个基本原则：扣减额度一定小于等于当前用户余额
        EcommerceBalance ecommerceBalance = balanceDao.findByUserId(loginUserInfo.getId());

        if (ecommerceBalance == null || ecommerceBalance.getBalance() < balanceInfo.getBalance()) {
            throw new RuntimeException("user balance is not enough!");
        }

        Long sourceBalance = ecommerceBalance.getBalance();
        Long deBalance = balanceInfo.getBalance();
        ecommerceBalance.setBalance(sourceBalance - deBalance);
        log.info("deduct user: [{}], source balance: [{}], deduct balance: [{}], new balance: [{}]",
                balanceDao.save(ecommerceBalance).getId(),
                sourceBalance,
                deBalance,
                ecommerceBalance.getBalance()
        );

        return new BalanceInfo(
                ecommerceBalance.getUserId(),
                ecommerceBalance.getBalance()
        );
    }
}
